package com.example.springboot2.service;

import com.example.springboot2.common.PageResult;
import com.example.springboot2.entity.LaundryOrder;
import com.example.springboot2.entity.LaundryService;
import com.example.springboot2.entity.Merchant;
import com.example.springboot2.exception.BusinessException;
import com.example.springboot2.repository.LaundryOrderRepository;
import com.example.springboot2.repository.LaundryServiceRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import jakarta.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 洗护业务服务类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LaundryBusinessService {

    private final LaundryServiceRepository laundryServiceRepository;
    private final LaundryOrderRepository laundryOrderRepository;
    private final MerchantService merchantService;

    // ===== 洗护服务管理 =====

    /**
     * 分页查询洗护服务列表
     */
    public PageResult<LaundryService> getLaundryServices(Long userId, Integer current, Integer size, 
                                                         String name, String serviceType) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        Pageable pageable = PageRequest.of(current - 1, size, 
                Sort.by(Sort.Direction.ASC, "sortOrder").and(Sort.by(Sort.Direction.DESC, "createdTime")));
        
        Specification<LaundryService> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 商家条件
            predicates.add(criteriaBuilder.equal(root.get("merchant"), merchant));
            
            // 服务名称模糊查询
            if (StringUtils.hasText(name)) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + name + "%"));
            }
            
            // 服务类型查询
            if (StringUtils.hasText(serviceType)) {
                predicates.add(criteriaBuilder.equal(root.get("serviceType"), 
                        LaundryService.ServiceType.valueOf(serviceType)));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<LaundryService> page = laundryServiceRepository.findAll(spec, pageable);
        return PageResult.of(page);
    }

    /**
     * 获取洗护服务详情
     */
    public LaundryService getLaundryServiceDetail(Long userId, Long serviceId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        LaundryService service = laundryServiceRepository.findById(serviceId)
                .orElseThrow(() -> new BusinessException("洗护服务不存在"));
        
        // 验证服务是否属于当前商家
        if (!service.getMerchant().getId().equals(merchant.getId())) {
            throw new BusinessException("无权访问该服务");
        }
        
        return service;
    }

    /**
     * 创建洗护服务
     */
    @Transactional
    public LaundryService createLaundryService(Long userId, LaundryService service) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        service.setMerchant(merchant);
        
        LaundryService savedService = laundryServiceRepository.save(service);
        log.info("商家创建洗护服务: {} - {}", merchant.getShopName(), service.getName());
        return savedService;
    }

    /**
     * 更新洗护服务
     */
    @Transactional
    public LaundryService updateLaundryService(Long userId, Long serviceId, LaundryService serviceInfo) {
        LaundryService existingService = getLaundryServiceDetail(userId, serviceId);
        
        // 更新服务信息
        existingService.setName(serviceInfo.getName());
        existingService.setDescription(serviceInfo.getDescription());
        existingService.setServiceType(serviceInfo.getServiceType());
        existingService.setPrice(serviceInfo.getPrice());
        existingService.setUnit(serviceInfo.getUnit());
        existingService.setEstimatedTime(serviceInfo.getEstimatedTime());
        existingService.setIcon(serviceInfo.getIcon());
        existingService.setTags(serviceInfo.getTags());
        existingService.setSortOrder(serviceInfo.getSortOrder());
        
        LaundryService savedService = laundryServiceRepository.save(existingService);
        log.info("商家更新洗护服务: {} - {}", existingService.getMerchant().getShopName(), serviceInfo.getName());
        return savedService;
    }

    /**
     * 删除洗护服务
     */
    @Transactional
    public void deleteLaundryService(Long userId, Long serviceId) {
        LaundryService service = getLaundryServiceDetail(userId, serviceId);
        
        laundryServiceRepository.delete(service);
        log.info("商家删除洗护服务: {} - {}", service.getMerchant().getShopName(), service.getName());
    }

    /**
     * 批量更新服务状态
     */
    @Transactional
    public void batchUpdateServiceStatus(Long userId, List<Long> serviceIds, Boolean isEnabled) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        for (Long serviceId : serviceIds) {
            LaundryService service = getLaundryServiceDetail(userId, serviceId);
            service.setIsEnabled(isEnabled);
            laundryServiceRepository.save(service);
        }
        
        log.info("商家批量更新洗护服务状态: {} - 数量: {} - 状态: {}", 
                merchant.getShopName(), serviceIds.size(), isEnabled ? "启用" : "禁用");
    }

    // ===== 洗护订单管理 =====

    /**
     * 分页查询洗护订单列表
     */
    public PageResult<LaundryOrder> getLaundryOrders(Long userId, Integer current, Integer size, 
                                                     String orderNo, String status) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        Pageable pageable = PageRequest.of(current - 1, size, 
                Sort.by(Sort.Direction.DESC, "createdTime"));
        
        Specification<LaundryOrder> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 商家条件
            predicates.add(criteriaBuilder.equal(root.get("merchant"), merchant));
            
            // 订单号查询
            if (StringUtils.hasText(orderNo)) {
                predicates.add(criteriaBuilder.like(root.get("orderNo"), "%" + orderNo + "%"));
            }
            
            // 状态查询
            if (StringUtils.hasText(status)) {
                predicates.add(criteriaBuilder.equal(root.get("status"), 
                        LaundryOrder.LaundryOrderStatus.valueOf(status)));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<LaundryOrder> page = laundryOrderRepository.findAll(spec, pageable);
        return PageResult.of(page);
    }

    /**
     * 获取洗护订单详情
     */
    public LaundryOrder getLaundryOrderDetail(Long userId, Long orderId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        LaundryOrder order = laundryOrderRepository.findById(orderId)
                .orElseThrow(() -> new BusinessException("洗护订单不存在"));
        
        // 验证订单是否属于当前商家
        if (!order.getMerchant().getId().equals(merchant.getId())) {
            throw new BusinessException("无权访问该订单");
        }
        
        return order;
    }

    /**
     * 接单
     */
    @Transactional
    public void acceptLaundryOrder(Long userId, Long orderId, LocalDateTime pickupTime) {
        LaundryOrder order = getLaundryOrderDetail(userId, orderId);
        
        if (order.getStatus() != LaundryOrder.LaundryOrderStatus.PENDING) {
            throw new BusinessException("订单状态不允许接单");
        }
        
        order.setStatus(LaundryOrder.LaundryOrderStatus.ACCEPTED);
        order.setAcceptedTime(LocalDateTime.now());
        order.setPickupTime(pickupTime);
        
        laundryOrderRepository.save(order);
        log.info("商家接单: {} - 订单号: {}", order.getMerchant().getShopName(), order.getOrderNo());
    }

    /**
     * 拒绝订单
     */
    @Transactional
    public void rejectLaundryOrder(Long userId, Long orderId, String reason) {
        LaundryOrder order = getLaundryOrderDetail(userId, orderId);
        
        if (order.getStatus() != LaundryOrder.LaundryOrderStatus.PENDING) {
            throw new BusinessException("订单状态不允许拒绝");
        }
        
        order.setStatus(LaundryOrder.LaundryOrderStatus.CANCELLED);
        order.setCancelledTime(LocalDateTime.now());
        order.setCancelReason(reason);
        
        laundryOrderRepository.save(order);
        log.info("商家拒绝订单: {} - 订单号: {} - 原因: {}", 
                order.getMerchant().getShopName(), order.getOrderNo(), reason);
    }

    /**
     * 更新洗护订单状态
     */
    @Transactional
    public void updateLaundryOrderStatus(Long userId, Long orderId, 
                                         LaundryOrder.LaundryOrderStatus status, String remark) {
        LaundryOrder order = getLaundryOrderDetail(userId, orderId);
        
        LaundryOrder.LaundryOrderStatus oldStatus = order.getStatus();
        order.setStatus(status);
        
        // 根据状态更新相应的时间字段
        LocalDateTime now = LocalDateTime.now();
        switch (status) {
            case PICKED_UP:
                order.setPickedUpTime(now);
                break;
            case IN_PROCESS:
                order.setProcessStartTime(now);
                break;
            case QUALITY_CHECK:
                order.setProcessEndTime(now);
                break;
            case READY:
                order.setQualityCheckTime(now);
                break;
            case DELIVERED:
                order.setDeliveredTime(now);
                break;
            case CANCELLED:
                order.setCancelledTime(now);
                order.setCancelReason(remark);
                break;
        }
        
        if (StringUtils.hasText(remark)) {
            order.setRemark(remark);
        }
        
        laundryOrderRepository.save(order);
        
        log.info("商家更新洗护订单状态: {} - 订单号: {} - {} -> {}", 
                order.getMerchant().getShopName(), order.getOrderNo(), oldStatus, status);
    }
}
